home *** CD-ROM | disk | FTP | other *** search
/ PC Direct 1998 August / PC Direct August 1998.iso / S / powerj / Product / hpp.z / WARRAY.HPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-25  |  14.2 KB  |  513 lines

  1. /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2.    %     Copyright (C) 1994, by WATCOM International Inc.  All rights    %
  3.    %     reserved.  No part of this software may be reproduced or        %
  4.    %     used in any form or by any means - graphic, electronic or       %
  5.    %     mechanical, including photocopying, recording, taping or        %
  6.    %     information storage and retrieval systems - except with the     %
  7.    %     written permission of WATCOM International Inc.                 %
  8.    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  9. */
  10.  
  11. #ifndef _WARRAY_HPP_INCLUDED
  12. #define _WARRAY_HPP_INCLUDED
  13. #pragma once
  14.  
  15. #ifndef _WNO_PRAGMA_PUSH
  16. #pragma pack(push,8);
  17. #pragma enum int;
  18. #endif
  19.  
  20. #ifndef _WOBJECT_HPP_INCLUDED
  21. #  include "wobject.hpp"
  22. #endif
  23. #ifndef _WDEBUG_HPP_INCLUDED
  24. #  include "wdebug.hpp"
  25. #endif
  26. #ifndef _WREFOBJ_HPP_INCLUDED
  27. #  include "wrefobj.hpp"
  28. #endif
  29.  
  30. /*************************************************************************
  31.  *
  32.  * WArrayReference
  33.  *
  34.  *************************************************************************/
  35.  
  36. template <class T>
  37. class WCMCLASS WArrayReference : public WReferenceObject {
  38.  
  39.         /**********************************************************
  40.          * Constructors and Destructors
  41.          *********************************************************/
  42.  
  43.         // This class is meant to be used as a reference class, with
  44.         // objects allocated via new.  As such we don't allow
  45.         // copies to be made except via the MakeCopy method.  New
  46.         // objects are allocated via the static function Allocate.
  47.     
  48.     private:
  49.         WArrayReference( const WArrayReference & ar );
  50.         WArrayReference & operator=( const WArrayReference & ar );
  51.  
  52.     protected:
  53.         WArrayReference( size_t count );
  54.  
  55.     public:
  56.         ~WArrayReference();
  57.  
  58.         /**********************************************************
  59.          * Properties
  60.          *********************************************************/
  61.  
  62.         // Count
  63.  
  64.         int   GetCount() const { return _count; }
  65.         WBool SetCount( int count );
  66.  
  67.         // Data
  68.  
  69.         T * GetData() const { return _objs; }
  70.  
  71.         // RealCount
  72.  
  73.         int GetRealCount() const;
  74.  
  75.         /**********************************************************
  76.          * Methods
  77.          *********************************************************/
  78.  
  79.         // Allocate
  80.         //
  81.         //    Allocates a new object.
  82.  
  83.         static WArrayReference *Allocate( size_t count );
  84.  
  85.         // MakeCopy
  86.         //
  87.         //    Creates a new memory object based on the current
  88.         //    one, copying the data.
  89.  
  90.         WArrayReference *MakeCopy( WInt newCount=-1 );
  91.  
  92.         /**********************************************************
  93.          * Private
  94.          *********************************************************/
  95.  
  96.     private:
  97.  
  98.         T *                     _objs;
  99.         int                     _count;
  100.         int                     _realCount;
  101. };
  102.  
  103. #if defined( _DEBUG ) && !defined( new )
  104.     #define _UNINCLUDE_NEW
  105.     #include "wnew.hpp"
  106. #endif
  107.  
  108. template<class T> WArrayReference<T>::WArrayReference( size_t count ) {
  109.     _count     = count;
  110.     _realCount = count;
  111.     _objs      = NULL;
  112.  
  113.     if( count > 0 ) {
  114.         _objs = new T[ count ];
  115.     }
  116. }
  117.  
  118. template<class T> WArrayReference<T>::~WArrayReference() {
  119.     delete [] _objs;
  120.  
  121.     _objs      = NULL;
  122.     _count     = 0;
  123.     _realCount = 0;
  124. }
  125.  
  126. template<class T> int WArrayReference<T>::GetRealCount() const {
  127.     return _realCount;
  128. }
  129.  
  130. template<class T> WBool WArrayReference<T>::SetCount( int count ) {
  131.     WASSERT( count <= _realCount && count >= 0 );
  132.     _count = count;
  133.     return TRUE;
  134. }
  135.  
  136. template<class T> static WArrayReference<T> * WArrayReference<T>::Allocate( size_t count ){
  137.     WArrayReference * ref;
  138.     ref = new WArrayReference<T>( count );
  139.     if( ref != NULL ) {
  140.         ref->Reference();
  141.         return ref;
  142.     }
  143.     return NULL;
  144. }
  145.  
  146. template<class T> WArrayReference<T>* WArrayReference<T>::MakeCopy( WInt newCount ){
  147.     WArrayReference *   ref;
  148.     WInt                desiredCount = newCount;
  149.  
  150.     if( newCount < 0 ) {
  151.         newCount = _realCount;
  152.     }
  153.     ref = new WArrayReference<T>( newCount );
  154.     WASSERT( ref != NULL );
  155.     if( ref != NULL ){
  156.         ref->Reference();
  157.         if( _realCount != 0 ) {
  158.             T *         oldData;
  159.             T *         newData;
  160.  
  161.             if( _realCount < newCount ) {
  162.                 newCount = _realCount;
  163.             }
  164.             oldData = GetData();
  165.             newData = ref->GetData();
  166.             for( int i = 0; i < newCount; i++ ) {
  167.                 newData[i] = oldData[i];
  168.             }
  169.         }
  170.         if( desiredCount < 0 ) {
  171.             ref->_count = _count;
  172.         } else {
  173.             ref->_count = desiredCount;
  174.         }
  175.     }
  176.     return ref; 
  177. }
  178.  
  179. /*************************************************************************
  180.  *
  181.  * WArray
  182.  *
  183.  *************************************************************************/
  184.  
  185.  
  186. template<class T>
  187. class WCMCLASS WArray {
  188.  
  189.     public:
  190.  
  191.         /**********************************************************
  192.          * Constructors and Destructors
  193.          *********************************************************/
  194.  
  195.         WArray();
  196.         WArray( const T & t );
  197.         WArray( const WArray & array );
  198.  
  199.         ~WArray();
  200.  
  201.         /**********************************************************
  202.          * Properties
  203.          *********************************************************/
  204.  
  205.         // Count
  206.         //
  207.         //    Returns the count of items in the array.
  208.  
  209.         inline WInt GetCount() const;
  210.         WBool       SetCount( WInt count );
  211.  
  212.         // Size
  213.         //
  214.         //    Returns the size (max # of items) of the array.
  215.  
  216.         WInt GetSize() const;
  217.  
  218.         /**********************************************************
  219.          * Operators
  220.          *********************************************************/
  221.  
  222.         inline const T & operator[]( int index ) const;
  223.         T & operator[]( int index );
  224.  
  225.         inline operator const T &() const;
  226.         operator T &();
  227.  
  228.         WArray & operator=( const T & t );
  229.         WArray & operator=( const WArray & array );
  230.  
  231.         /**********************************************************
  232.          * Methods
  233.          *********************************************************/
  234.  
  235.         // Lock
  236.         //
  237.         //    Lock the array for direct manipulation, possibly growing
  238.         //    it at the same time.  Ensures that no one else is
  239.         //    referencing the array.
  240.  
  241.         T* Lock( WInt count=-1 );
  242.  
  243.         // Unlock
  244.         //
  245.         //    Unlock the array after direct manipulation.
  246.  
  247.         void Unlock();
  248.  
  249.         /**********************************************************
  250.          * Other
  251.          *********************************************************/
  252.  
  253.         WInt GetRealCount() const;
  254.  
  255.         static const T & GetOutOfBoundsValue();
  256.         static T &       GetDummyValue();
  257.  
  258.         /**********************************************************
  259.          * Data Members
  260.          *********************************************************/
  261.  
  262.     protected:
  263.  
  264.         WArrayReference< T > *_arrRef;
  265. };
  266.  
  267. template<class T> static const T & WArray<T>::GetOutOfBoundsValue(){
  268.     static T _outOfBoundsValue;
  269.     return _outOfBoundsValue;
  270. }
  271.  
  272. template<class T> static T & WArray<T>::GetDummyValue(){
  273.     static T _dummyValue;
  274.     return _dummyValue;
  275. }
  276.  
  277. template<class T> WArray<T>::WArray(){
  278.     _arrRef = WArrayReference<T>::Allocate( 0 );
  279.     WASSERT( _arrRef != NULL );
  280. }
  281.  
  282. template<class T> WArray<T>::WArray( const T & t ) {
  283.     _arrRef = WArrayReference<T>::Allocate( 1 );
  284.     WASSERT( _arrRef != NULL );
  285.     if( _arrRef ) _arrRef->GetData()[0] = t;
  286. }
  287.  
  288. template<class T> WArray<T>::WArray( const WArray<T> & array ) {
  289.     _arrRef = array._arrRef;
  290.     WASSERT( _arrRef != NULL );
  291.     if( _arrRef ) _arrRef->Reference();
  292. }
  293.  
  294. template<class T> WArray<T>::~WArray() {
  295.     WASSERT( _arrRef != NULL );
  296.     _arrRef->Unreference();
  297. }
  298.  
  299. template<class T> WBool WArray<T>::SetCount( WInt count ) {
  300.     WASSERT( _arrRef != NULL );
  301.     if( count <= GetSize() && _arrRef->GetReferenceCount() == 1 ) {
  302.         return _arrRef->SetCount( count );
  303.     } else {
  304.         WArrayReference<T> *    newRef = _arrRef->MakeCopy( count );
  305.         _arrRef->Unreference();
  306.         _arrRef = newRef;
  307.         return TRUE;
  308.     }
  309. }
  310.  
  311. template<class T> WInt WArray<T>::GetCount() const {
  312.     WASSERT( _arrRef != NULL );
  313.     return _arrRef->GetCount();
  314. }
  315.  
  316. template<class T> WInt WArray<T>::GetRealCount() const {
  317.     return GetSize();
  318. }
  319.  
  320. template<class T> WInt WArray<T>::GetSize() const {
  321.     WASSERT( _arrRef != NULL );
  322.     return _arrRef->GetRealCount();
  323. }
  324.  
  325. template<class T> const T & WArray<T>::operator[]( int index ) const {
  326.     WASSERTEX( _arrRef && index < _arrRef->GetCount(), "Array index out of bounds" );
  327.     if( !_arrRef || index < 0 || index >= _arrRef->GetCount() ){
  328.         return GetOutOfBoundsValue();
  329.     }
  330.     return _arrRef->GetData()[index];
  331. }
  332.  
  333. template<class T> T & WArray<T>::operator[]( int index ){
  334.     WASSERTEX( _arrRef && index < _arrRef->GetCount(), "Array index out of bounds" );
  335.     if( !_arrRef || index < 0 || index >= _arrRef->GetCount() ){
  336.         return GetDummyValue();
  337.     }
  338.     WArrayReference<T> * oldArrRef = _arrRef;
  339.     if( _arrRef->GetReferenceCount() > 1 ){
  340.         _arrRef = _arrRef->MakeCopy();
  341.         oldArrRef->Unreference();
  342.     }
  343.     return _arrRef->GetData()[index];
  344. }
  345.  
  346. template<class T> WArray<T>::operator const T&() const {
  347.     WASSERTEX( _arrRef && _arrRef->GetCount() > 0, "Empty array" );
  348.     if( !_arrRef || _arrRef->GetCount() == 0 ){
  349.         return GetOutOfBoundsValue();
  350.     }
  351.     return _arrRef->GetData()[0];
  352. }
  353.  
  354. template<class T> WArray<T>::operator T&(){
  355.     WASSERTEX( _arrRef && _arrRef->GetCount() > 0, "Empty array" );
  356.     if( !_arrRef || _arrRef->GetCount() == 0 ){
  357.         return GetDummyValue();
  358.     }
  359.     WArrayReference<T> * oldArrRef = _arrRef;
  360.     if( _arrRef->GetReferenceCount() > 1 ) {
  361.         _arrRef = _arrRef->MakeCopy();
  362.         oldArrRef->Unreference();
  363.     }
  364.     return _arrRef->GetData()[0];
  365. }
  366.  
  367. template<class T> WArray<T> & WArray<T>::operator=( const T & t ){
  368.     if( _arrRef ) _arrRef->Unreference();
  369.     _arrRef = WArrayReference<T>::Allocate( 1 );
  370.     if( _arrRef ) _arrRef->GetData()[0] = t;
  371.     return *this;
  372. }
  373.  
  374. template<class T> WArray<T> & WArray<T>::operator=( const WArray<T> & array ){
  375.     if( this != &array ){
  376.         WArrayReference<T> *old = _arrRef;
  377.         _arrRef = array._arrRef;
  378.         if( _arrRef) _arrRef->Reference();
  379.         if( old ) old->Unreference();
  380.     }
  381.     return *this;
  382. }
  383.  
  384. template<class T> T* WArray<T>::Lock( WInt count ){
  385.     WASSERT( _arrRef );
  386.     if( count < 0 ){
  387.         count = GetCount();
  388.     }
  389.     if( count == 0 ){
  390.         count = 1;
  391.     }
  392.     SetCount( count ); 
  393.     WASSERT( _arrRef->GetReferenceCount() == 1 );
  394.     WASSERT( _arrRef->GetData() != NULL );
  395.     return _arrRef->GetData();
  396. }
  397.  
  398. template<class T> void WArray<T>::Unlock(){
  399.     WASSERT( _arrRef );
  400.     // nothing to do...
  401. }
  402.  
  403. typedef int WCMDEF (*WArraySysCompRtn)( const void *, const void * );
  404.  
  405. extern int              WArrayCompare( const void *, const void * );
  406. extern WArraySysCompRtn WArrayCompareRoutine;
  407. extern void             WArrayAcquire();
  408. extern void             WArrayRelease();
  409.  
  410. template<class T>
  411. class WCMCLASS WSortableArray : public WArray<T> {
  412.  
  413.     public:
  414.  
  415.         typedef int WCMDEF (*WArrayCompareRoutine)( const T *, const T * );
  416.  
  417.     public:
  418.  
  419.         /**********************************************************
  420.          * Constructors and Destructors
  421.          *********************************************************/
  422.  
  423.         WSortableArray();
  424.         WSortableArray( const T & t );
  425.         WSortableArray( const WArray & array );
  426.  
  427.         ~WSortableArray();
  428.  
  429.         /**********************************************************
  430.          * Methods
  431.          *********************************************************/
  432.  
  433.         // Sort
  434.         //
  435.         //    Sorts the array using qsort.  First locks it, then sorts.
  436.         //    If no sort function is provided, sorts in ascending
  437.         //    order using '<' and '==' operators.
  438.  
  439.         void Sort( WArrayCompareRoutine routine=NULL );
  440.  
  441.         static int DefaultCompare( const T *, const T * );
  442. };
  443.  
  444. template<class T> WSortableArray<T>::WSortableArray() : WArray() {
  445. }
  446.  
  447. template<class T> WSortableArray<T>::WSortableArray( const T & t )
  448.   : WArray( t ) {
  449. }
  450.  
  451. template<class T> WSortableArray<T>::WSortableArray( const WArray & array )
  452.   : WArray( array ) {
  453. }
  454.  
  455. template<class T> WSortableArray<T>::~WSortableArray() {
  456. }
  457.  
  458. template<class T> static WSortableArray<T>::DefaultCompare( const T *l, const T *r ){
  459.     if( *l < *r ){
  460.         return -1;
  461.     } else if( *l == *r ){
  462.         return 0;
  463.     } else {
  464.         return 1;
  465.     }
  466. }
  467.  
  468. template<class T> void WSortableArray<T>::Sort( WArrayCompareRoutine routine ){
  469.     int count = GetCount();
  470.     if( !_arrRef || count == 0 ) return;
  471.     if( !routine ) routine = DefaultCompare;
  472.     WArrayAcquire();
  473.     T *data = Lock();
  474.     WArrayCompareRoutine = (WArraySysCompRtn) routine;
  475.     qsort( data, count, sizeof( T ), WArrayCompare );
  476.     Unlock();
  477.     WArrayRelease();
  478. }
  479.  
  480. //
  481. // Standard array types
  482. //
  483.  
  484. extern template WArrayReference<WInt>;
  485. extern template WArray<WInt>;
  486. typedef WArray<WInt>                    WIntArray;
  487.  
  488. extern template WArrayReference<WULong>;
  489. extern template WArray<WULong>;
  490. typedef WArray<WULong>                  WULongArray;
  491.  
  492. extern template WArrayReference<WLong>;
  493. extern template WArray<WLong>;
  494. typedef WArray<WLong>                   WLongArray;
  495.  
  496. extern template WArrayReference<WBool>;
  497. extern template WArray<WBool>;
  498. typedef WArray<WBool>                   WBoolArray;
  499.  
  500. #if defined( _UNINCLUDE_NEW )
  501.     #undef new
  502.     #undef delete
  503.     #undef WNew
  504.     #undef WDelete
  505. #endif
  506.  
  507. #ifndef _WNO_PRAGMA_PUSH
  508. #pragma enum pop;
  509. #pragma pack(pop);
  510. #endif
  511.  
  512. #endif // _WARRAY_HPP_INCLUDED
  513.